package pro.cherish.knowledgeschedule.jdkTimer;

/**
 * @author 创建人：cherish
 * @version 版本号：V1.0
 * <p>
 * ***************************修订记录************************************
 * 2019-11-05 cherish 创建该类功能。
 * **********************************************************************
 * </p>
 * @ClassName 类名：TimerDemo
 * @Description 功能说明：
 * <p>
 * TODO
 * </p>
 * **********************************************************************
 * @date 创建日期： 2019-11-05 cherish
 */
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

/**
 * 作用：利用JDK中原始的Timer，处理定时任务
 * 主要有如下四大方法：
 * 		系统启动后，延迟delay毫秒后，执行定时任务
 * 			schedule(TimerTask task,long delay)
 *
 * 		系统启动后，系统时间达到(或当前时间超过)指定时间date后，执行定时任务
 * 			schedule(TimerTask task,Date date)
 *
 * 		系统启动后，延迟delay毫秒后，执行定时任务，并每间隔period毫秒执行
 * 			schedule(TimerTask task, long delay, long period)
 *
 * 		系统启动后，除了在设定的时间执行定时任务外，还会每间隔period毫秒执行
 * 			schedule(TimerTask task, Date date, long period)
 *
 * @author xiaoshiniudao_lq
 *
 */
public class TimerDemo {

    public static void main(String[] args) throws ParseException {
//		执行一次();
		执行多次();
//         指定时间();
//		执行间隔();
    }

    /**
     * 说明：定时任务用到了线程，调用schedule(TimerTask task,long delay)
     * 定时任务之所以能在指定的时间点执行，是因为在指定时间唤醒了线程(任务)，让其具有获取CPU片段的资格，但可能不会立即执行，其误差可忽略不计。
     *
     */
    public static void 执行一次() {
        System.out.println("*****************************************************");
        //创建计时器
        Timer timer = new Timer("开始执行任务-------------------");
        //创建计时器任务(TimerTaskBean:是自定义的类，继承了TimerTask抽象类)
        TimerTask task = new TimerTaskBean();
        //调用计时器的schedule方法（时间表），此处的1000代表：在当前时间的1000毫秒之后，此线程会被唤醒
        timer.schedule(task, 5000);
        System.out.println("定时任务已启动，于5秒后执行");
        System.out.println("*****************************************************");
    }

    /**
     * 说明：执行多次定时任务：是为了体现就算当时间点到达的时候，不一定先被唤醒的定时任务（或线程）就会被立即执行
     */
    public static void 执行多次() {
        for(int i=1;i<11;i++){
            Timer timer = new Timer("任务 - "+i);
            TimerTask task = new TimerTaskBean();
            timer.schedule(task, 3000);
            System.out.println("第" + i + "次任务，已启动，于3秒后执行");
        }
        System.out.println("-------------任务启动完毕，等待执行-----------");
    }

    /**
     * 作用：指定当前系统日期的19:06:59去执行任务，如果当前时间大于设定的时间，定时任务会被立即启动
     * 说明：调用schedule(TimerTask task,Date date)方法，指定时间运行任务
     *
     */
    public static void 指定时间() {
        Date date = 获取时间();
        if(date!=null){
            System.out.println("Date时间："+date);
            Timer timer = new Timer("开始执行-------------------------");
            System.out.println("*****************定时器已启动*****************");
            TimerTask task = new TimerTaskBean();
            timer.schedule(task, date);
        }else{
            System.out.println("*****************定时器启动失败*****************");
        }
    }

    /**
     * 作用：当指定时间达到后执行，并在此基础上每间隔2秒执行一次。
     */
    public static void 执行间隔() {
        Date date = 获取时间();
        if(date!=null){
            Timer timer = new Timer("开始执行-------------------------");
            System.out.println("*****************定时器已启动*****************");
            TimerTask task = new TimerTaskBean();
            timer.schedule(task, date, 2000);
        }else{
            System.out.println("*****************定时器启动失败*****************");
        }
    }

    /**
     * 作用：获取时间，或者说返回指定时间
     * @return date 时间
     */
    private static Date 获取时间() {
        Calendar c = Calendar.getInstance();
        int mon =  c.get(Calendar.MONTH)==12?1:c.get(Calendar.MONTH)+1;
        String stringDate = c.get(Calendar.YEAR) +"-"+ mon +"-"+ c.get(Calendar.DATE) + " ";
        stringDate = stringDate + "19:06:59";
        System.out.println("String时间 ："+stringDate);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date=null;
        try {
            date = (Date) dateFormat.parse(stringDate);
        } catch (Exception e) {
            date=null;
        }
        return date;
    }
}